﻿// -----------------------------------------------------------------------
// <copyright file="HumanoFormModel.cs" company="Storytelling">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------
namespace Storytelling.Modelos
{
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.Linq;
    using Storytelling.Entidades;
    using Storytelling.Modelos.Utils;
    using Storytelling.Utils;

    public class HumanoFormModel : NomeadoFormModel<Humano>, IEvolucaoFormModel
    {
        private static IDictionary<TipoCampo, string> evolucaoOpcoes;

        private string cronica;
        private string[] humanoEspecializacaoEspecializacao;
        private string[] humanoVantagemVantagem;
        private string[] humanoDesvantagemDesvantagem;
        private string[] humanoArmaArma;
        private string[] humanoItemItem;

        public int? TipoEntidade { get; set; }

        static HumanoFormModel()
        {
            evolucaoOpcoes = new Dictionary<TipoCampo, string>();
            evolucaoOpcoes.Add(TipoCampo.Especializacao, "Especialização");
            evolucaoOpcoes.Add(TipoCampo.Vantagem, "Vantagem");
        }

        protected override Humano CriadorEntidade
        {
            get
            {
                Humano humano = null;

                if (TipoEntidade.HasValue)
                {
                    humano = CriadorTipoEntidade.Instancia.Criar(TipoEntidade.Value);
                }

                if (humano != null)
                {
                    return humano;
                }
                else
                {
                    return base.CriadorEntidade;
                }
            }
        }

        public override long? Id
        {
            get { return base.Id; }
            set { base.Id = value; }
        }

        public virtual string Jogador { get; set; }

        public virtual string Cronica
        {
            get 
            {
                if (Entidade.Cronica != null && !string.IsNullOrEmpty(Entidade.Cronica.Nome))
                {
                    cronica = Entidade.Cronica.Nome;
                }
                else
                {
                    cronica = "";
                }
                return cronica; 
            }
            set { cronica = value; }
        }

        [Required]
        [Display(Name = "Crônica")]
        public virtual long CronicaValor
        {
            get { return Entidade.CronicaId; }
            set { Entidade.CronicaId = value; }
        }

        [Required]
        [Display(Name = "Virtude")]
        public virtual int Virtude
        {
            get { return Entidade.Virtude.HasValue ? (int)Entidade.Virtude.Value : 0; }
            set { Entidade.Virtude = (Virtude)value; }
        }

        [Required]
        [Display(Name = "Vício")]
        public virtual int Vicio
        {
            get { return Entidade.Vicio.HasValue ? (int)Entidade.Vicio.Value : 0; }
            set { Entidade.Vicio = (Vicio)value; }
        }

        [Display(Name = "Tamanho")]
        public virtual int? Tamanho
        {
            get { return (int?)Entidade.Tamanho; }
            set { Entidade.Tamanho = value.HasValue ? (Tamanho)value.Value : Entidades.Tamanho.Adulto; }
        }

        [Range(1, 10, ErrorMessage = "A Moralidade deve ser de 1 a 10")]
        [Display(Name = "Moralidade")]
        public virtual int? Moralidade
        {
            get { return Entidade.Moralidade > 0 ? Entidade.Moralidade : 7; }
            set { Entidade.Moralidade = value.HasValue ? value.Value : 7; }
        }

        [Display(Name = "Vitalidade")]
        public virtual string Vitalidade
        {
            get 
            {
                if (Entidade.Penalidade.HasValue && Entidade.Penalidade.Value != Penalidade.Nenhum)
                {
                    return string.Format("{0} (-{1})", Entidade.Vitalidade, (int)Entidade.Penalidade.Value); 
                }
                else
                {
                    return Entidade.Vitalidade.ToString(); 
                }
            }
        }

        [Display(Name = "Força de Vontade")]
        public virtual string Vontade
        {
            get { return string.Format("{0} / {1}", Entidade.VontadeTemporaria.HasValue ? (int)Entidade.VontadeTemporaria.Value : 0, Entidade.Vontade); }
        }

        [Display(Name = "Contusão")]
        public virtual int DanoContusao
        {
            get 
            {
                return Entidade.DanoContusao.HasValue && Entidade.DanoLetal.HasValue ?
                (Entidade.DanoContusao.Value - Entidade.DanoLetal.Value) : 0;
            }
        }

        [Display(Name = "Letal")]
        public virtual int DanoLetal
        {
            get 
            { 
                return Entidade.DanoLetal.HasValue && Entidade.DanoAgravado.HasValue ? 
                (Entidade.DanoLetal.Value - Entidade.DanoAgravado.Value) : 0; 
            }
        }

        [Display(Name = "Agravado")]
        public virtual int DanoAgravado
        {
            get { return Entidade.DanoAgravado.HasValue ? Entidade.DanoAgravado.Value : 0; }
        }

        [Display(Name = "Deslocamento")]
        public int Deslocamento
        {
            get { return Entidade.Forca + Entidade.Destreza + 5; }
        }

        [Display(Name = "Iniciativa")]
        public int Iniciativa
        {
            get { return Entidade.Destreza + Entidade.Autocontrole; }
        }

        [Display(Name = "Defesa")]
        public int Defesa 
        {
            get { return Entidade.Destreza > Entidade.Raciocinio ? Entidade.Raciocinio : Entidade.Destreza; }
        }

        [Display(Name = "Experiência")]
        public virtual int Experiencia
        {
            get { return Entidade.Experiencia; }
        }

        public virtual IDictionary<TipoCampo, string> Opcoes
        {
            get { return evolucaoOpcoes; }
        }

        public virtual string ConfigurarAutocompleteEvolucao
        {
            get { return "configurarAutocompleteEvolucao"; }
        }

        #region Atributos

        [Required]
        [Range(1, 9, ErrorMessage = "O Força deve ser de 1 a 9")]
        [Display(Name = "Força")]
        public virtual int Forca
        {
            get { return Entidade.Forca; }
            set { Entidade.Forca = value; }
        }

        [Required]
        [Range(1, 9, ErrorMessage = "A Destreza deve ser de 1 a 9")]
        [Display(Name = "Destreza")]
        public virtual int Destreza
        {
            get { return Entidade.Destreza; }
            set { Entidade.Destreza = value; }
        }

        [Required]
        [Range(1, 9, ErrorMessage = "O Vigor deve ser de 1 a 9")]
        [Display(Name = "Vigor")]
        public virtual int Vigor
        {
            get { return Entidade.Vigor; }
            set { Entidade.Vigor = value; }
        }

        [Required]
        [Range(1, 9, ErrorMessage = "A Presença deve ser de 1 a 9")]
        [Display(Name = "Presença")]
        public virtual int Presenca
        {
            get { return Entidade.Presenca; }
            set { Entidade.Presenca = value; }
        }

        [Required]
        [Range(1, 9, ErrorMessage = "A Manipulação deve ser de 1 a 9")]
        [Display(Name = "Manipulação")]
        public virtual int Manipulacao
        {
            get { return Entidade.Manipulacao; }
            set { Entidade.Manipulacao = value; }
        }

        [Required]
        [Range(1, 9, ErrorMessage = "O Autocontrole deve ser de 1 a 9")]
        [Display(Name = "Autocontrole")]
        public virtual int Autocontrole
        {
            get { return Entidade.Autocontrole; }
            set { Entidade.Autocontrole = value; }
        }

        [Required]
        [Range(1, 9, ErrorMessage = "A Inteligência deve ser de 1 a 9")]
        [Display(Name = "Inteligência")]
        public virtual int Inteligencia
        {
            get { return Entidade.Inteligencia; }
            set { Entidade.Inteligencia = value; }
        }

        [Required]
        [Range(1, 9, ErrorMessage = "O Raciocínio deve ser de 1 a 9")]
        [Display(Name = "Raciocínio")]
        public virtual int Raciocinio
        {
            get { return Entidade.Raciocinio; }
            set { Entidade.Raciocinio = value; }
        }

        [Required]
        [Range(1, 9, ErrorMessage = "A Perseverança deve ser de 1 a 9")]
        [Display(Name = "Perseverança")]
        public virtual int Perseveranca
        {
            get { return Entidade.Perseveranca; }
            set { Entidade.Perseveranca = value; }
        }

        #endregion

        #region Habilidades

        [Required]
        [Range(0, 9, ErrorMessage = "O Armamento deve ser de 0 a 9")]
        [Display(Name = "Armamento")]
        public virtual int Armamento
        {
            get { return Entidade.Armamento.HasValue ? Entidade.Armamento.Value : 0; }
            set { Entidade.Armamento = value; }
        }

        [Required]
        [Range(0, 9, ErrorMessage = "A Arma de Fogo deve ser de 0 a 9")]
        [Display(Name = "Arma de Fogo")]
        public virtual int ArmasDeFogo
        {
            get { return Entidade.ArmasDeFogo.HasValue ? Entidade.ArmasDeFogo.Value : 0; }
            set { Entidade.ArmasDeFogo = value; }
        }

        [Required]
        [Range(0, 9, ErrorMessage = "A Briga deve ser de 0 a 9")]
        [Display(Name = "Briga")]
        public virtual int Briga
        {
            get { return Entidade.Briga.HasValue ? Entidade.Briga.Value : 0; }
            set { Entidade.Briga = value; }
        }

        [Required]
        [Range(0, 9, ErrorMessage = "A Condução deve ser de 0 a 9")]
        [Display(Name = "Condução")]
        public virtual int Conducao
        {
            get { return Entidade.Conducao.HasValue ? Entidade.Conducao.Value : 0; }
            set { Entidade.Conducao = value; }
        }

        [Required]
        [Range(0, 9, ErrorMessage = "A Dissimulação deve ser de 0 a 9")]
        [Display(Name = "Dissimulação")]
        public virtual int Dissimulacao
        {
            get { return Entidade.Dissimulacao.HasValue ? Entidade.Dissimulacao.Value : 0; }
            set { Entidade.Dissimulacao = value; }
        }

        [Required]
        [Range(0, 9, ErrorMessage = "Os Esportes deve ser de 0 a 9")]
        [Display(Name = "Esportes")]
        public virtual int Esportes
        {
            get { return Entidade.Esportes.HasValue ? Entidade.Esportes.Value : 0; }
            set { Entidade.Esportes = value; }
        }

        [Required]
        [Range(0, 9, ErrorMessage = "O Furto deve ser de 0 a 9")]
        [Display(Name = "Furto")]
        public virtual int Furto
        {
            get { return Entidade.Furto.HasValue ? Entidade.Furto.Value : 0; }
            set { Entidade.Furto = value; }
        }

        [Required]
        [Range(0, 9, ErrorMessage = "A Sobrevivência deve ser de 0 a 9")]
        [Display(Name = "Sobrevivência")]
        public virtual int Sobrevivencia
        {
            get { return Entidade.Sobrevivencia.HasValue ? Entidade.Sobrevivencia.Value : 0; }
            set { Entidade.Sobrevivencia = value; }
        }

        [Required]
        [Range(0, 9, ErrorMessage = "A Astúcia deve ser de 0 a 9")]
        [Display(Name = "Astúcia")]
        public virtual int Astucia
        {
            get { return Entidade.Astucia.HasValue ? Entidade.Astucia.Value : 0; }
            set { Entidade.Astucia = value; }
        }

        [Required]
        [Range(0, 9, ErrorMessage = "A Empatia deve ser de 0 a 9")]
        [Display(Name = "Empatia")]
        public virtual int Empatia
        {
            get { return Entidade.Empatia.HasValue ? Entidade.Empatia.Value : 0; }
            set { Entidade.Empatia = value; }
        }

        [Required]
        [Range(0, 9, ErrorMessage = "A Expressão deve ser de 0 a 9")]
        [Display(Name = "Expressão")]
        public virtual int Expressao
        {
            get { return Entidade.Expressao.HasValue ? Entidade.Expressao.Value : 0; }
            set { Entidade.Expressao = value; }
        }

        [Required]
        [Range(0, 9, ErrorMessage = "A Intimidação deve ser de 0 a 9")]
        [Display(Name = "Intimidação")]
        public virtual int Intimidacao
        {
            get { return Entidade.Intimidacao.HasValue ? Entidade.Intimidacao.Value : 0; }
            set { Entidade.Intimidacao = value; }
        }

        [Required]
        [Range(0, 9, ErrorMessage = "A Manha deve ser de 0 a 9")]
        [Display(Name = "Manha")]
        public virtual int Manha
        {
            get { return Entidade.Manha.HasValue ? Entidade.Manha.Value : 0; }
            set { Entidade.Manha = value; }
        }

        [Required]
        [Range(0, 9, ErrorMessage = "A Persuasão deve ser de 0 a 9")]
        [Display(Name = "Persuasão")]
        public virtual int Persuasao
        {
            get { return Entidade.Persuasao.HasValue ? Entidade.Persuasao.Value : 0; }
            set { Entidade.Persuasao = value; }
        }

        [Required]
        [Range(0, 9, ErrorMessage = "A Socialização deve ser de 0 a 9")]
        [Display(Name = "Socialização")]
        public virtual int Socializacao
        {
            get { return Entidade.Socializacao.HasValue ? Entidade.Socializacao.Value : 0; }
            set { Entidade.Socializacao = value; }
        }

        [Required]
        [Range(0, 9, ErrorMessage = "O Trato com Animais deve ser de 0 a 9")]
        [Display(Name = "Trato com Animais")]
        public virtual int TratoAnimais
        {
            get { return Entidade.TratoAnimais.HasValue ? Entidade.TratoAnimais.Value : 0; }
            set { Entidade.TratoAnimais = value; }
        }

        [Required]
        [Range(0, 9, ErrorMessage = "A Ciência deve ser de 0 a 9")]
        [Display(Name = "Ciência")]
        public virtual int Ciencias
        {
            get { return Entidade.Ciencias.HasValue ? Entidade.Ciencias.Value : 0; }
            set { Entidade.Ciencias = value; }
        }

        [Required]
        [Range(0, 9, ErrorMessage = "A Erudição deve ser de 0 a 9")]
        [Display(Name = "Erudição")]
        public virtual int Erudicao
        {
            get { return Entidade.Erudicao.HasValue ? Entidade.Erudicao.Value : 0; }
            set { Entidade.Erudicao = value; }
        }

        [Required]
        [Range(0, 9, ErrorMessage = "A Informática deve ser de 0 a 9")]
        [Display(Name = "Informática")]
        public virtual int Informatica
        {
            get { return Entidade.Informatica.HasValue ? Entidade.Informatica.Value : 0; }
            set { Entidade.Informatica = value; }
        }

        [Required]
        [Range(0, 9, ErrorMessage = "A Investigação deve ser de 0 a 9")]
        [Display(Name = "Investigação")]
        public virtual int Investigacao
        {
            get { return Entidade.Investigacao.HasValue ? Entidade.Investigacao.Value : 0; }
            set { Entidade.Investigacao = value; }
        }

        [Required]
        [Range(0, 9, ErrorMessage = "A Medicina deve ser de 0 a 9")]
        [Display(Name = "Medicina")]
        public virtual int Medicina
        {
            get { return Entidade.Medicina.HasValue ? Entidade.Medicina.Value : 0; }
            set { Entidade.Medicina = value; }
        }

        [Required]
        [Range(0, 9, ErrorMessage = "O Ocultismo deve ser de 0 a 9")]
        [Display(Name = "Ocultismo")]
        public virtual int Ocultismo
        {
            get { return Entidade.Ocultismo.HasValue ? Entidade.Ocultismo.Value : 0; }
            set { Entidade.Ocultismo = value; }
        }

        [Required]
        [Range(0, 9, ErrorMessage = "Os Ofícios deve ser de 0 a 9")]
        [Display(Name = "Ofícios")]
        public virtual int Oficios
        {
            get { return Entidade.Oficios.HasValue ? Entidade.Oficios.Value : 0; }
            set { Entidade.Oficios = value; }
        }

        [Required]
        [Range(0, 9, ErrorMessage = "A Política deve ser de 0 a 9")]
        [Display(Name = "Política")]
        public virtual int Politica
        {
            get { return Entidade.Politica.HasValue ? Entidade.Politica.Value : 0; }
            set { Entidade.Politica = value; }
        }

        #endregion

        #region Especializacoes

        public virtual long[] HumanoEspecializacaoId
        {
            get
            {
                return Entidade.Especializacoes != null ? Entidade.Especializacoes.Select(ent => ent.Id).ToArray() : new long[0];
            }
            set
            {
                Entidade.Transferidor<Humano, HumanoEspecializacao, long>(value, ent => ent.Especializacoes, (valor, item) =>
                {
                    item.HumanoId = Entidade.Id;
                    item.Id = valor;
                });
            }
        }

        public virtual string[] HumanoEspecializacaoEspecializacao
        {
            get
            {
                Entidade.CarregarArray<Humano, HumanoEspecializacao>(ref humanoEspecializacaoEspecializacao, ent => ent.Especializacoes, item => item.Especializacao);
                return humanoEspecializacaoEspecializacao;
            }
            set { humanoEspecializacaoEspecializacao = value; }
        }

        [ArrayRange(3, default(long))]
        [Display(Name = "Especialização")]
        public virtual long[] HumanoEspecializacaoEspecializacaoValor
        {
            get
            {
                return Entidade.Especializacoes != null ? Entidade.Especializacoes.Select(ent => ent.EspecializacaoId).ToArray() : new long[0];
            }
            set
            {
                Entidade.Transferidor<Humano, HumanoEspecializacao, long>(value, ent => ent.Especializacoes, (valor, item) =>
                {
                    item.HumanoId = Entidade.Id;
                    item.EspecializacaoId = valor;
                });
            }
        } 

        #endregion

        #region Vantagens

        public virtual long[] HumanoVantagemId
        {
            get
            {
                return Entidade.Vantagens != null ? Entidade.Vantagens.Select(ent => ent.Id).ToArray() : new long[0];
            }
            set
            {
                Entidade.Transferidor<Humano, HumanoVantagem, long>(value, ent => ent.Vantagens, (valor, item) =>
                {
                    item.HumanoId = Entidade.Id;
                    item.Id = valor;
                });
            }
        }

        public virtual string[] HumanoVantagemVantagem
        {
            get
            {
                Entidade.CarregarArray<Humano, HumanoVantagem>(ref humanoVantagemVantagem, ent => ent.Vantagens, item => item.Vantagem);
                return humanoVantagemVantagem;
            }
            set { humanoVantagemVantagem = value; }
        }

        [ArrayRange(0, default(long))]
        [Display(Name = "Vantagem")]
        public virtual long[] HumanoVantagemVantagemValor
        {
            get
            {
                return Entidade.Vantagens != null ? Entidade.Vantagens.Select(ent => ent.VantagemId).ToArray() : new long[0];
            }
            set
            {
                Entidade.Transferidor<Humano, HumanoVantagem, long>(value, ent => ent.Vantagens, (valor, item) =>
                {
                    item.HumanoId = Entidade.Id;
                    item.VantagemId = valor;
                });
            }
        }

        [ArrayRange(0, default(int))]
        [Display(Name = "Nível")]
        public virtual int[] HumanoVantagemVantagemNivel
        {
            get
            {
                return Entidade.Vantagens != null ? Entidade.Vantagens.Select(ent => ent.Nivel).ToArray() : new int[0];
            }
            set
            {
                Entidade.Transferidor<Humano, HumanoVantagem, int>(value, ent => ent.Vantagens, (valor, item) =>
                {
                    item.HumanoId = Entidade.Id;
                    item.Nivel = valor;
                });
            }
        }

        #endregion

        #region Desvantagens

        public virtual long[] HumanoDesvantagemId
        {
            get
            {
                return Entidade.Desvantagens != null ? Entidade.Desvantagens.Select(ent => ent.Id).ToArray() : new long[0];
            }
            set
            {
                Entidade.Transferidor<Humano, HumanoDesvantagem, long>(value, ent => ent.Desvantagens, (valor, item) =>
                {
                    item.HumanoId = Entidade.Id;
                    item.Id = valor;
                });
            }
        }

        public virtual string[] HumanoDesvantagemDesvantagem
        {
            get 
            {
                Entidade.CarregarArray<Humano, HumanoDesvantagem>(ref humanoDesvantagemDesvantagem, ent => ent.Desvantagens, item => item.Desvantagem);
                return humanoDesvantagemDesvantagem; 
            }
            set { humanoDesvantagemDesvantagem = value; }
        }

        [Display(Name = "Desvantagem")]
        public virtual long[] HumanoDesvantagemDesvantagemValor
        {
            get
            {
                return Entidade.Desvantagens != null ? Entidade.Desvantagens.Select(ent => ent.DesvantagemId).ToArray() : new long[0];
            }
            set
            {
                Entidade.Transferidor<Humano, HumanoDesvantagem, long>(value, ent => ent.Desvantagens, (valor, item) =>
                {
                    item.HumanoId = Entidade.Id;
                    item.DesvantagemId = valor;
                });
            }
        }

        [Display(Name = "Tipo")]
        public virtual int[] HumanoDesvantagemTipo
        {
            get
            {
                return Entidade.Desvantagens != null ? Entidade.Desvantagens.Select(ent => (int) ent.Tipo).ToArray() : new int[0];
            }
            set
            {
                Entidade.Transferidor<Humano, HumanoDesvantagem, int>(value, ent => ent.Desvantagens, (valor, item) =>
                {
                    item.HumanoId = Entidade.Id;
                    item.Tipo = (TipoDesvantagem) valor;
                });
            }
        }

        #endregion        
        
        #region Armas

        public virtual long[] HumanoArmaId
        {
            get
            {
                return Entidade.Armas != null ? Entidade.Armas.Select(ent => ent.Id).ToArray() : new long[0];
            }
            set
            {
                Entidade.Transferidor<Humano, HumanoArma, long>(value, ent => ent.Armas, (valor, item) =>
                {
                    item.HumanoId = Entidade.Id;
                    item.Id = valor;
                });
            }
        }

        public virtual string[] HumanoArmaArma
        {
            get 
            {
                Entidade.CarregarArray<Humano, HumanoArma>(ref humanoArmaArma, ent => ent.Armas, item => item.Arma);
                return humanoArmaArma; 
            }
            set { humanoArmaArma = value; }
        }

        [Display(Name = "Arma")]
        public virtual long[] HumanoArmaArmaValor
        {
            get
            {
                return Entidade.Armas != null ? Entidade.Armas.Select(ent => ent.ArmaId).ToArray() : new long[0];
            }
            set
            {
                Entidade.Transferidor<Humano, HumanoArma, long>(value, ent => ent.Armas, (valor, item) =>
                {
                    item.HumanoId = Entidade.Id;
                    item.ArmaId = valor;
                });
            }
        }

        #endregion

        #region Itens

        public virtual long[] HumanoItemId
        {
            get
            {
                return Entidade.Itens != null ? Entidade.Itens.Select(ent => ent.Id).ToArray() : new long[0];
            }
            set
            {
                Entidade.Transferidor<Humano, HumanoItem, long>(value, ent => ent.Itens, (valor, item) =>
                {
                    item.HumanoId = Entidade.Id;
                    item.Id = valor;
                });
            }
        }

        public string[] HumanoItemItem
        {
            get 
            {
                Entidade.CarregarArray<Humano, HumanoItem>(ref humanoItemItem, ent => ent.Itens, item => item.Item);
                return humanoItemItem; 
            }
            set { humanoItemItem = value; }
        }

        [Display(Name = "Item")]
        public virtual long[] HumanoItemItemValor
        {
            get
            {
                return Entidade.Itens != null ? Entidade.Itens.Select(ent => ent.ItemId).ToArray() : new long[0];
            }
            set
            {
                Entidade.Transferidor<Humano, HumanoItem, long>(value, ent => ent.Itens, (valor, item) =>
                {
                    item.HumanoId = Entidade.Id;
                    item.ItemId = valor;
                });
            }
        }

        #endregion
    }
}
